#include "CCanvas.h"
#include "Base.h"
#include "Timer.h"

#include <iostream>
#include <fstream>
using namespace std;

//-----------------------------------------------------------------------------

void CCanvas::initializeGL()
{
  glClearColor(1.0f, 1.0f, 1.0f, 0.5f);			          // White Background
  glClearDepth(1.0f);									                // Depth Buffer Setup
  glEnable(GL_DEPTH_TEST);							              // Enables Depth Testing
  glDepthFunc(GL_LEQUAL);								              // The Type Of Depth Testing To Do
  glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);	// Really Nice Perspective Calculations

  //
  // read off file
  //
  ifstream in("icosahedron_0.off");
	if (!in) {
		cout<<"\nError reading file."<<endl;
		exit(0);
	}
  string s;
	getline(in,s);
	if (s!="OFF") {
		cout<<"\nThis is not a valid OFF file."<<endl;
		exit(0);
	}
	int i, numV, numT, dummy;
	in >> numV >> numT >> dummy;
  
	v.resize(numV);
  for (i=0; i<numV; i++)
		in >> v[i][0] >> v[i][1] >> v[i][2];

  t.resize(numT);
	for (i=0; i<numT; i++)
		in >> dummy >> t[i].v[0] >> t[i].v[1] >> t[i].v[2];

	in.close();
};

//-----------------------------------------------------------------------------

void CCanvas::resizeGL(int width, int height)
{
  // set up the window-to-viewport transformation
  glViewport( 0,0, width,height );

  // vertical camera opening angle
  double beta = 90.0;

  // aspect ratio
  double gamma;
  if (height > 0)
    gamma = width/(double)height;
  else
    gamma = width;

  // front and back clipping plane at
  double n = -1.0;
  double f = -10.0;

  // set projection matrix
  glMatrixMode(GL_PROJECTION);
  glLoadIdentity();
  gluPerspective( beta, gamma, -n, -f );

};
  
//-----------------------------------------------------------------------------

void CCanvas::paintGL()
{
  // clear screen and depth buffer
  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

  // set model-view matrix
  glMatrixMode(GL_MODELVIEW);
  glLoadIdentity();
  gluLookAt( 0,0,0,  0,0,-1,  0,1,0 );     // camera position , "look at" point , view-up vector

  // set up a light source
  GLfloat ambient [] = { 0.6, 0.6, 0.6, 1.0 };
  GLfloat diffuse [] = { 1.0, 1.0, 1.0, 1.0 };
  GLfloat specular[] = { 1.0, 1.0, 1.0, 1.0 };
  GLfloat position[] = { -10.0, 5.0, 5.0, 1.0 };

  glLightfv( GL_LIGHT0, GL_AMBIENT,  ambient  );
  glLightfv( GL_LIGHT0, GL_DIFFUSE,  diffuse  );
  glLightfv( GL_LIGHT0, GL_SPECULAR, specular );
  glLightfv( GL_LIGHT0, GL_POSITION, position );

  // turn on light
  glEnable( GL_NORMALIZE );
  glEnable( GL_LIGHTING );
  glEnable( GL_LIGHT0 );

  // choose between flat and Gouraud shading
  glShadeModel( GL_FLAT );
//  glShadeModel( GL_SMOOTH );

  // set up a sphere
  GLUquadricObj *sphere;
  sphere = gluNewQuadric();
  gluQuadricDrawStyle( sphere, GLU_FILL );

  // set material coefficients
  GLfloat mat_emission[] = { 0.0, 0.0, 0.0, 0.0 }; 
  GLfloat mat_ambient [] = { 0.2, 0.2, 0.2, 1.0 };
  GLfloat mat_diffuse [] = { 0.8, 0.2, 0.2, 1.0 };
  GLfloat mat_specular[] = { 0.5, 0.5, 0.5, 1.0 };
  
  glMaterialfv( GL_FRONT, GL_EMISSION, mat_emission );
  glMaterialfv( GL_FRONT, GL_AMBIENT,  mat_ambient  );
  glMaterialfv( GL_FRONT, GL_DIFFUSE,  mat_diffuse  );
  glMaterialfv( GL_FRONT, GL_SPECULAR, mat_specular );
  glMaterialf ( GL_FRONT, GL_SHININESS, 40.0 );

  // transform and draw sphere
  glPushMatrix();
  glTranslated (-3.0, 0.0, -10.0);	
	glScaled (2.0, 2.0, 2.0);
	glRotated ( tau, 1,0,0 );
  gluSphere( sphere, 1.0, 20,10 );
  glPopMatrix();

  // transform and draw icosahedron
  glTranslated (3.0, 0.0, -10.0);	
	glScaled (2.0, 2.0, 2.0);
	glRotated ( tau, 0,1,0 );

  glBegin( GL_TRIANGLES );
  for (int i=0; i<t.size(); i++) {

    // triangle normal for flat shading  
    Point3d N = ( v[t[i].v[1]] - v[t[i].v[0]] ) ^ ( v[t[i].v[2]] - v[t[i].v[0]] );
    N.normalize();
    glNormal3d( N.x(), N.y(), N.z() );

    for (int j=0; j<3; j++) {
      Point3d& V = v[t[i].v[j]];
      // vertex normal for Gouraud shading
//      glNormal3d( V.x(), V.y(), V.z() );
      glVertex3d( V.x(), V.y(), V.z() );
    }
  }
  glEnd( );

  tau += 1.0;
}